'use client';

import { type ChangeEvent, type FormEvent, useEffect, useState } from 'react';
import { useMutation } from '@tanstack/react-query';
import diff from 'microdiff';
import type {
  IConfigOauthClient,
  IDifference,
  IYwOauthClient,
} from '@/interfaces';
import { updateOauthClientConfig } from '@/services/api';
import classNames from 'classnames';
import useToast from '@/hooks/useToast';
import { nanoid } from 'nanoid';
import { getDiffData } from '@/lib/tool';
import Box from '@/app/[locale]/admin/common/box';
import Spinner from '@/app/[locale]/component/spinner/spinner';
import Nodata from '@/app/[locale]/common/nodata/nodata';
import type { PrefixedTTranslatedFields } from '@/lib/dictionaries';

export default function UpdateConfigOauthClient(
  this: any,
  {
    source,
    translatedFields,
  }: {
    source: IConfigOauthClient;
    translatedFields: PrefixedTTranslatedFields<'configAdminPage'>;
  },
) {
  const { show } = useToast();
  const [form, setForm] = useState<{
    showMenuEntry: boolean;
    doc?: string;
  }>({
    showMenuEntry: source.showMenuEntry ?? true,
    doc: source.doc ?? '',
  });
  const [clients, setClients] = useState<IYwOauthClient[]>([]);
  const [clientForm, setClientForm] = useState<IYwOauthClient>({
    enable: false,
    clientId: '',
    clientSecret: '',
    redirectUri: '',
    scope: '',
    state: '',
    clientName: '',
    clientSite: '',
    clientLogo: '',
    imagePathPrefix: '',
    remark: '',
  });
  const [differenceData, setDifferenceData] = useState<IDifference[]>([]);
  const [tabIndex, setTabIndex] = useState(0);
  const [currentClientItem, setCurrentClientItem] = useState<IYwOauthClient>();
  const [isDisabledSave, setIsDisabledSave] = useState(true);

  const updateOauthClientConfigMutation = useMutation(updateOauthClientConfig);

  useEffect(() => {
    const diffData = diff(
      {
        showMenuEntry: source.showMenuEntry ?? true,
        doc: source.doc ?? '',
        ywClients: source.ywClients,
      },
      {
        ...form,
        ywClients: clients,
      },
    );
    setDifferenceData(diffData);
    setIsDisabledSave(diffData.length === 0);
  }, [clients, form, source]);

  async function onClickSave(e: FormEvent<HTMLFormElement>) {
    try {
      e.preventDefault();
      e.stopPropagation();

      const data = getDiffData(differenceData);
      await updateOauthClientConfigMutation.mutateAsync({
        data: {
          ...data,
          ywClients: clients,
        },
      });

      show({
        type: 'SUCCESS',
        message: translatedFields.operate.updateCompleted,
      });
    } catch (e) {
      updateOauthClientConfigMutation.reset();
      show({
        type: 'DANGER',
        message: e,
      });
    } finally {
      setDifferenceData([]);
    }
  }

  function onClickTab(index: number) {
    setTabIndex(index);
  }

  function onClickSaveItem() {
    const { clientId, redirectUri } = clientForm;
    if (!clientId) {
      show({
        type: 'DANGER',
        message: translatedFields.config.client.clientIdRequired,
      });
      return;
    } else if (clients.find((item) => item.clientId === clientId)) {
      show({
        type: 'DANGER',
        message: translatedFields.config.client.clientIdExisted,
      });
      return;
    }

    if (!redirectUri) {
      show({
        type: 'DANGER',
        message: translatedFields.config.client.redirectUriRequired,
      });
      return;
    }

    let scope = clientForm.scope;
    if (!scope) {
      scope = 'getUserInfo';
    }

    let state = clientForm.state;
    if (!state) {
      state = nanoid();
    }

    let clientSecret = clientForm.clientSecret;
    if (!clientSecret) {
      clientSecret = nanoid();
    }

    setClients([
      ...clients,
      {
        ...clientForm,
        clientSecret,
        scope,
        state,
      },
    ]);

    show({
      type: 'PRIMARY',
      message: translatedFields.operate.addCompleted,
    });
  }

  function onClickUpdateItem(item: IYwOauthClient) {
    setCurrentClientItem(item);
    setClientForm({
      ...item,
      remark: item.remark || '',
    });
  }

  function onClickSaveUpdateItem() {
    if (!currentClientItem) {
      show({
        type: 'DANGER',
        message: translatedFields.config.client.dataDoesNotExist,
      });
      return;
    }

    setClients([
      ...clients.filter((item) => item.clientId !== currentClientItem.clientId),
      {
        ...currentClientItem,
        ...clientForm,
      },
    ]);
  }

  function onClickRemoveItem(item: IYwOauthClient) {
    setClients([
      ...clients.filter((value) => value.clientId !== item.clientId),
    ]);
  }

  function onChangeForm(
    e: ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>,
  ) {
    const name = e.target.name;
    const value = e.target.value;

    if (name === 'showMenuEntry') {
      setForm({ ...form, showMenuEntry: value === 'true' });
    } else {
      setForm({ ...form, [name]: value });
    }
  }

  function onChangeClientForm(
    e: ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>,
  ) {
    const name = e.target.name;
    const value = e.target.value;

    if (name === 'enable') {
      setClientForm({ ...clientForm, enable: value === 'true' });
    } else {
      setClientForm({ ...clientForm, [name]: value });
    }
  }

  return (
    <Box>
      <div className="vstack gap-4">
        <nav className="nav nav-pills flex-column flex-sm-row mb-4 mt-2">
          <a
            onClick={onClickTab.bind(this, 0)}
            className={classNames(
              'flex-sm-fill text-sm-center nav-link cursor-pointer',
              {
                'bg-light': tabIndex === 0,
              },
            )}
          >
            {translatedFields.config.client.basic}
          </a>
          <a
            onClick={onClickTab.bind(this, 1)}
            className={classNames(
              'flex-sm-fill text-sm-center nav-link cursor-pointer',
              {
                'bg-light': tabIndex === 1,
              },
            )}
          >
            {translatedFields.config.client.list}
          </a>
        </nav>

        {tabIndex === 0 && (
          <form onSubmit={onClickSave} className="vstack gap-4">
            <div>
              <label className="form-label">
                {translatedFields.config.client.showMenuEntry}
              </label>
              <select
                name="showMenuEntry"
                value={form.showMenuEntry + ''}
                onChange={onChangeForm}
                className="form-select"
                aria-label="showMenuEntry"
              >
                <option value="true">true</option>
                <option value="false">false</option>
              </select>
            </div>

            <div>
              <label className="form-label">
                {translatedFields.config.client.doc}
              </label>
              <textarea
                rows={1}
                className="form-control"
                name="doc"
                value={form.doc}
                onChange={onChangeForm}
                aria-describedby="doc"
              />
            </div>

            <button
              type="submit"
              disabled={
                updateOauthClientConfigMutation.isLoading || isDisabledSave
              }
              className="btn btn-success col col-lg-2 my-4"
            >
              {updateOauthClientConfigMutation.isLoading && (
                <Spinner classs="me-2" />
              )}
              {translatedFields.operate.update}
            </button>
          </form>
        )}

        {tabIndex === 1 && (
          <form onSubmit={onClickSave} className="vstack gap-4">
            {clients.length > 0 && (
              <div className="table-responsive">
                <table className="table table-hover align-middle">
                  <thead>
                    <tr className="text-nowrap">
                      <th className="fw-normal" scope="col">
                        {translatedFields.config.client.enable}
                      </th>
                      <th className="fw-normal" scope="col">
                        {translatedFields.config.client.clientId}
                      </th>
                      <th className="fw-normal" scope="col">
                        {translatedFields.config.client.clientSecret}
                      </th>
                      <th className="fw-normal" scope="col">
                        {translatedFields.config.client.scope}
                      </th>
                      <th className="fw-normal" scope="col">
                        {translatedFields.config.client.state}
                      </th>
                      <th className="fw-normal" scope="col"></th>
                    </tr>
                  </thead>
                  <tbody>
                    {clients.map((item) => {
                      return (
                        <tr
                          key={item.clientId}
                          className={classNames({
                            active:
                              item.clientId === currentClientItem?.clientId,
                          })}
                        >
                          <td className="text-nowrap">{item.enable + ''}</td>
                          <th className="text-nowrap" scope="row">
                            {item.clientId}
                          </th>
                          <td className="text-nowrap">{item.clientSecret}</td>
                          <td className="text-nowrap">{item.scope}</td>
                          <td className="text-nowrap">{item.state}</td>
                          <td className="text-nowrap hstack gap-4">
                            <button
                              onClick={onClickUpdateItem.bind(this, item)}
                              type="button"
                              className="btn btn-primary btn-sm"
                            >
                              <i className="bi bi-pencil-square me-2"></i>
                              {translatedFields.operate.update}
                            </button>
                            <button
                              onClick={onClickRemoveItem.bind(this, item)}
                              type="button"
                              className="btn btn-danger btn-sm"
                            >
                              <i className="bi bi-trash me-2"></i>
                              {translatedFields.operate.delete}
                            </button>
                          </td>
                        </tr>
                      );
                    })}
                  </tbody>
                </table>
              </div>
            )}

            {clients.length === 0 && <Nodata />}

            <div className="card">
              <div className="card-body">
                <div className="vstack gap-4">
                  <div>
                    <label className="form-label">
                      {translatedFields.config.client.enable}
                    </label>
                    <select
                      name="enable"
                      value={clientForm.enable ? 'true' : 'false'}
                      onChange={onChangeClientForm}
                      className="form-select"
                      aria-label="enable"
                    >
                      <option value="true">true</option>
                      <option value="false">false</option>
                    </select>
                  </div>

                  <div>
                    <label className="form-label">
                      {translatedFields.config.client.clientId}
                    </label>
                    <input
                      type="text"
                      className="form-control"
                      name="clientId"
                      value={clientForm.clientId}
                      onChange={onChangeClientForm}
                      aria-describedby="clientId"
                    />
                  </div>

                  <div>
                    <label className="form-label"></label>
                    <input
                      type="text"
                      className="form-control"
                      name="clientSecret"
                      value={clientForm.clientSecret}
                      onChange={onChangeClientForm}
                      aria-describedby="clientSecret"
                    />
                  </div>

                  <div>
                    <label className="form-label">
                      {translatedFields.config.client.redirectUri}
                    </label>
                    <textarea
                      rows={1}
                      className="form-control"
                      name="redirectUri"
                      value={clientForm.redirectUri}
                      onChange={onChangeClientForm}
                      aria-describedby="redirectUri"
                    />
                  </div>

                  <div>
                    <label className="form-label">
                      {translatedFields.config.client.scope}
                    </label>
                    <textarea
                      rows={1}
                      className="form-control"
                      name="scope"
                      value={clientForm.scope}
                      onChange={onChangeClientForm}
                      aria-describedby="scope"
                    />
                  </div>

                  <div>
                    <label className="form-label">
                      {translatedFields.config.client.state}
                    </label>
                    <input
                      type="text"
                      className="form-control"
                      name="state"
                      value={clientForm.state}
                      onChange={onChangeClientForm}
                      aria-describedby="state"
                    />
                  </div>

                  <div>
                    <label className="form-label">
                      {translatedFields.config.client.clientName}
                    </label>
                    <input
                      type="text"
                      className="form-control"
                      name="clientName"
                      value={clientForm.clientName}
                      onChange={onChangeClientForm}
                      aria-describedby="clientName"
                    />
                  </div>

                  <div>
                    <label className="form-label">
                      {translatedFields.config.client.clientSite}
                    </label>
                    <textarea
                      rows={1}
                      className="form-control"
                      name="clientSite"
                      value={clientForm.clientSite}
                      onChange={onChangeClientForm}
                      aria-describedby="clientSite"
                    />
                  </div>

                  <div>
                    <label className="form-label">
                      {translatedFields.config.client.clientLogo}
                    </label>
                    <textarea
                      rows={1}
                      className="form-control"
                      name="clientLogo"
                      value={clientForm.clientLogo}
                      onChange={onChangeClientForm}
                      aria-describedby="clientLogo"
                    />
                  </div>

                  <div>
                    <label className="form-label">
                      {translatedFields.config.client.imagePathPrefix}
                    </label>
                    <input
                      type="text"
                      className="form-control"
                      name="imagePathPrefix"
                      value={clientForm.imagePathPrefix}
                      onChange={onChangeClientForm}
                      aria-describedby="imagePathPrefix"
                    />
                  </div>

                  <div>
                    <label className="form-label">
                      {translatedFields.config.client.remark}
                    </label>
                    <textarea
                      rows={1}
                      className="form-control"
                      name="remark"
                      value={clientForm.remark}
                      onChange={onChangeClientForm}
                      aria-describedby="remark"
                    />
                  </div>

                  <div>
                    {currentClientItem ? (
                      <button
                        onClick={onClickSaveUpdateItem}
                        type="button"
                        className="btn col col-lg-2 my-4 btn-primary"
                      >
                        <i className="bi bi-save2 me-2"></i>
                        {translatedFields.operate.save}
                      </button>
                    ) : (
                      <button
                        onClick={onClickSaveItem}
                        type="button"
                        className="btn col col-lg-2 my-4 btn-primary"
                      >
                        <i className="bi bi-plus-lg me-2"></i>
                        {translatedFields.operate.add}
                      </button>
                    )}
                  </div>
                </div>
              </div>
            </div>

            <button
              type="submit"
              disabled={
                updateOauthClientConfigMutation.isLoading || isDisabledSave
              }
              className="btn btn-success col col-lg-2 my-4"
            >
              {updateOauthClientConfigMutation.isLoading && (
                <Spinner classs="me-2" />
              )}
              {translatedFields.operate.update}
            </button>
          </form>
        )}
      </div>
    </Box>
  );
}
